"""The one worker→main-thread channel.

Cinema 4D forbids GUI work, scene mutation, and EventAdd off the main thread;
the documented push pattern is `c4d.SpecialEventAdd(id)` from the worker and a
`CoreMessage` drain on the main thread. Every background producer in this hub
(sign-in flow, verdict refresh, catalog fetch, tool download) funnels through
this queue so the dialog has exactly one drain point.
"""

from __future__ import annotations

import queue

import c4d
import c4d.threading

from . import prefs

QUEUE: "queue.Queue[tuple]" = queue.Queue()

_workers: list = []  # keep C4DThread refs alive while they run


class _Worker(c4d.threading.C4DThread):
    """Run one callable off-main — Maxon's preferred thread wrapper."""

    def __init__(self, target):
        super().__init__()
        self._target = target

    def Main(self):
        self._target()


def spawn(target):
    worker = _Worker(target)
    _workers.append(worker)
    worker.Start()
    return worker


def push(kind: str, payload=None) -> None:
    """Queue an event and wake the main thread. Safe from any thread."""
    QUEUE.put((kind, payload))
    c4d.SpecialEventAdd(prefs.HUB_ID)


def drain() -> list[tuple]:
    items = []
    while True:
        try:
            items.append(QUEUE.get_nowait())
        except queue.Empty:
            return items
